5. ÕPPEMATERJAL - graafika ja animatsioonid
graafika ja animatsioonid
| Õpikeskkond: | Tartu Ülikooli Moodle´i õpikeskkond |
| Kursus: | Teeme ise arvutimänge (MTAT.TK.008) |
| Raamat: | 5. ÕPPEMATERJAL - graafika ja animatsioonid |
| Printija: | Jaan Janno |
| Kuupäev: | neljapäev, 18. mai 2017, 12.51 |
Sisukord
RAAMAT 5


Kursuse "Teeme ise arvutimänge - algus"
5. RAAMAT
GRAAFIKA JA ANIMATSIOON
Tiina Kull
Tartu Ülikool
2012
Graafika

Lõpuks ometi GRAAFIKA juurde! Usu, kui ma ise kunagi ammu
programmeerimisega alustasin, siis tundusid kõik need harjutused alguses
kohutavalt tüütud ja kuidagi magedad, sest algsetel programmidel ei
tundunud mitte mingit pistmist olevat nende programmidega, mida saab
internetis mängida ja mida saab poest osta. Nüüd tagant järele
targutades, saan aru küll, et kui pole põhikonstruktsioonidest ja
algoritmilisest mõtlemisest mingit aimu, siis ei tee ka palja
graafikagagi suurt midagi. Mis mu jutu moraal on
, ikka see, et loodan, et sa oled siiani kenasti vastu pidanud ja endale korraliku vundamendi ladunud.
Graafika loomiseks võtame appi juba valmis paketi programme (Pygame), mis aitavad meil asju ekraanile panna, neid liikuma panna, joonistada maastikke, panna juurde heli ja kõike muud mängude juurde kuuluvat.
Miks kasutada Pygame?
Ilma
Pygame'ta oleks graafika tööle saamine üsna keeruline töö isegi
tavaprogrammeerija jaoks, sest siin tuleb arvestada juba väga paljude
erinevate arvuti osadega, mitte lihtsalt arvuti mäluga. Tuleb arvestada
operatsioonisüsteemiga, sest kõikides op-süsteemides on heli ja pildi
lahendused veidi erinevad, tuleb arvestada erinevate heli- ja
graafikakaartidega, protsessorite kiirusega jpm sellisega.
Põhimõtteliselt peaksime tundma õppima kõigi erinevate jubinate
hingeelu, nende eripära, kuidas nendega suheldakse jne, mis on üks väga
suur ettevõtmine ja võtab tavaliselt aastaid, kui sellel alal päris
spetsiks saada.
Pygame on aga paljude programmeeriate poolt koostatud ja õpetatud suhtlema erinevate kaartide ja op-süsteemidega, nii et meie eest on väga suur töö ära tehtud ning meil ei jäägi midagi muud üle kui nautida eelmiste programmeerijate töö vilju. Pealegi on see tasuta!
Pygame on sul juba arvutisse installeritud ja ka esimesed katsetused eelmisel ja üle-eelmisel nädalal tehtud. Sellel nädalal aga uurime ükispulki järele, kuidas ikkagi neid komponente koostatakse, akna moodustamisest kuni asjade liikuma panemiseni ekraanil ja nende juhtimiseni klaviatuuri või hiirega.
Akna loomine
Esimene asi mängu realiseerimisel on akna loomine - piirkond, kus mäng toimuma hakkab. Selleks on vaja kirjutada neli rida:



Selle koodi tööle panemisel võisid näha väikest vilksatust, kuid mitte midagi muud. Mis toimub? Pygame on loodud mängude tegemiseks ja mängude juures on väga oluline see, et midagi toimuks. Mängudes ei juhtu mitte midagi ilma mängija käskudeta. Pygame'i käima panemisel hakkab vaikimisi tööle nn sündmuste kontrolli tsükkel, mis pidevalt kontrollib, kas midagi mängus tehakse või mitte. Kas vajutatakse mingit klahvi või liigutatakse hiirt? Niipea kui sündmuste kontrollija lõpetab töö, lõpetatakse automaatselt ka kogu programmi töö. Meie oma nelja reaga, ei võtnud kontrolli sündmuste kontrolli tsükli üle, seetõttu ta ka nii ruttu asjad kokku pakkis.
Mängu töö tagamiseks tuleb alati kirjutada programmi sisse selline tsükkel, mis kontrollib seda, millal kasutaja mängu kinni paneb. Samuti tasub while tsükli järele lisada rida pygame.quit(), mis aitab vähendada Thonny ja Pygame omavahelist konflikti.
Teeme seda - kirjutame sellise tsükli, mis töötab, kuni on aken käsitsi sulgetud.

Mängu tsükkel
Enamasti on mängude südameks üks tsükkel, mis töötab kuni mängu sulgumiseni. See teeb jooksvalt kõike, mida näed oma ekraanil toimumas - tihti mitukümmend korda sekundis, et mängu liikumine tunduks sujuv.
Selline tsükkel koosneb klassikaliselt 3 faasist.
- Sisendite kogumine - näiteks klahvivajutuste või hiireliigutuste tuvastamine.
- Mängu "olukorra" uuendamine - sisuliselt näiteks erinevate objektide asukoha muutmine vastavalt kiirusele jne. See toimub tihti mõjutatuna varasemalt kogutud kasutaja sisenditest.
- Joonistamise faas - võttes arvesse kõiki sisendeid ning mängu olukorda, joonistatakse selleele vastav pilt.
Näide:
- Esimeses faasis tuvastab rallimäng, et mängija vajutas vasakule klahvi.
- Uuenduse faasis muutub auto asukohta tähistav muutuja vastavalt selliselt, et koordinaadistikus asub ta vasemal.
- Joonistamise faasis joonistatakse auto juba vastavalt uuele asukohale.
- Ja tagasi esimesse faasi - tsükkel jätkub.

Siin ka video, milles väike näide.
Videos arutatud lõpptulemuseks on järgmine kood:

Joonistamine aknasse
Joonistamist
Pygames kasutatakse tavaliselt maastiku loomiseks ja mitte tegelaste
loomiseks. Tegelased, kes mängudes ringi jooksevad või asjad, mida
tegelased korjavad, on tavaliselt juba valmis pildid, mis on eelnevalt
valmis joonistatud mõnes joonistusprogrammis. (Oluline on joonistada
erinevate tegelaste erinevad asendid - seismine, paremale jooksmine,
vasakule jooksmine, ronimine vms.). Joonistamise alla pygames kuuluvad
värvide, kujundite, joonte jm taolise kasutamine. Vaatame, kuidas seda
tehakse?
Esimesed katsetused joonistamiseks
Muudame
kõigepealt ekraani tausta valgeks ja seejärel lisame ekraanile punase
ringi, rohelise ristküliku ja sinise joone. Kujundite ükshaaval
testimiseks peab kindlasti kirjutama ka juurde rea pygame.display.flip(), mis uuendab ekraani pilti.

Kõiki pygame.draw võimalusi ei ole mõtet siin selle väikese lehe peal välja tuua. Hea ülevaate kõikidest pygame.draw võimalustest leiad Pythoni pygame dokumentatsiooni lehelt, kus on iga funktsiooni juurde kirjutatud, mida ta teha oskab ja millised argumendid, millises järjekorras tuleb sulgudesse kirjutada:
Akna koordinaadid
Haa, või arvad, et tead, kuidas koordinaatide kaudu ekraanile kujundeid lisada? Arvad, et tead, mis asi on koordinaatteljestik?
Asi pole sugugi nii lihtne vaid tegelikult palju lihtsam
kui koolimatemaatika koordinaatteljestik. Pygame koordinaatteljestik ei ole traditsiooniline rist x- ja y-teljest, mis jaotavad kogu ala neljaks veerandiks. Ei, pygame (0, 0) punkt asub mitte ekraani keskel vaid ALATI üleval vasakus nurgas. X-telg liigub paremale ja y-telg
liigub alla. Kujundite või piltide positsioneerimiseks ekraanil tuleb
arvestada alati loendamisest ülevalt vasakust nurgast. Järjekord punkti
koordinaatides on aga ikka samasugune - kõigepealt x-telje koordinaat ja siis y-telje koordinaat.
Värvid
Värvide
defineerimiseks kasutatakse programmeerimises ja nii ka pygame-s
kolmest arvust koosnevat kombinatsiooni, mida nimetatakse RGB-süsteemiks. Esimene arv näitab punase (Red) doseeringut, teine arv näitab rohelise (Green) doseeringut ja viimane arv näitab sinise (Blue)
kontsentratsiooni. Iga värvi saab muuta 0-st 255-ni. Mida suurem on
arv, seda rohkem on seda värvi lõpptulemuses. Kui kõik arvud keerata
0-i, siis saame musta värvi ehk värvitu tulemuse ja kui kõik värvid
keerame maksimumi peale ehk 255-le, siis saame valge värvi. Kõik
ülejäänud värvid saame erinevatest kombinatsioonidest. Kui keerata kõik
arvud ühesuguseks, näiteks [100, 100, 100], siis saame halli tooni. Mida
suuremad on ühesugused arvud, seda heledama halli saame, mida
väiksemad, seda tumedama.
Tegelikult on pygame-s ka nimekiri üle 600 värvinimetusega, kui sa ei peaks tahtma kasutada RGB-süsteemi. Kõik nimed koos värvi näidisega leiad siit:
https://sites.google.com/site/meticulosslacker/pygame-thecolors
Kujundite omavaheline ühendamine
Nüüd räägin sulle pygame.draw-s ühest trikitamise võimalusest, mis aitab kujundeid omavahel paiknemise suhtes siduda. Mida see tähendab?
Oletame, et ma olen keset ekraani joonistanud ristküliku või ruudu ja ma tahan täpselt selle ruudu keskele joonistada ringi, siis on väga tülikas hakata välja arvutama xy-koordinaatsüsteemis ringi keskpunkti kooridinaate. Siin tulebki appi üks pygme.draw objekt nimega Rect. Põhimõtteliselt on see sama, mis ristküliku loomise käsk, kuid teda saab kasutada ka eraldi, andes talle parameetriteks ainult koordinaadi vasakult, koorinaadi ülevalt, laiuse ja kõrguse. Kui selline objekt on defineeritud, saab käskida tema suhtes paiknema panna teisi kujundeid järgmiste käskudega:
- külgede suhtes: top, left, bottom, right
- nurkade suhtes: topleft, bottomleft, topright, bottomright
- keskel äärtes: midtop, midleft, midbottom, midright
- keskel: center, centerx, centery
- suurus: size, width, height
Uuri näidet ja proovi järgi:


Oluline on mõista seda, et Rect'i võib defineerida mistahes kohta ja mistahes suurusega, kuid ei pea
selle defineeritud ristküliku reaalselt ekraanile välja joonistama. Nii
võin üle kogu ekraani defineerida mitmeid kaste ja kastikesi, millede
kaudu saan hiljem teisi kujundeid kergemini positsioneerida ja üksteise
suhtes paigutada. Sellepärast ma kutsungi seda trikitamiseks.
Kujundite raamid
Erinevate
kujundite joonistamise viimaseks parameetriks on raami paksus. Kõikides
eelnevates näidetes kasutasime raami paksuseks 0-i. See tähendab seda,
et kujund ei joonistata üldse mitte raamiga vaid täidetakse tervenisti
värviga. Kui muuta see arv nullist suuremaks, siis joonistatakse ainult
selle kujundi välispiir ja seest jäetakse tühjaks. Piiri paksus oleneb
arvu suurusest. Tee katseid erinevate raami suurustega!
Mullid!


Et raamidega jändamine oleks huvitavam, katseta antud näidet - igal käivitamisel tuleb erinev tulemus.
Eriti ilusa tulemuse korral salvesta
Vaba käega joon
Mäletate
neid mänge paberil, kus on terve rida punkte numbritega ja need tuleb
nubrite järgi ühendada, mille tulemusel tekib mingi vahva pilt.
Vabakäelise joone tegemine pygame-s käib täpselt sama moodi. Kõigepealt
peab eelnevalt tekitama punktide joru, mida tahetakse joonega ühendada
ja siis kasutatakse pygame.draw käsku lines.
Punktide jada pannakse kirja tavaliselt listi, sest selles on punktide
ühendamise järjekord juba määratud. Mida tihedamalt on punkte listi
kirjutatud, seda sujuvam joon tuleb.
Teeme paar näidet:


Sujuva joone tegemiseks tuleks punktid panna üsna tihedalt, kuid seda on käsitsi teha üsna aeganõudev. Seega mõne tuntud sujuva joone tegemiseks kasutatakse tavaliselt matemaatiliste funktsioonide abi punktipaaride konstrueerimisel. Proovime joonistada näiteks laineid sinusoidi abil:

Tekst
Teksti ekraanile trükkimiseks ei pea tegema mitte midagi üleloomulikku. Kui oled ka ussimängu eelnevalt täpselt uurinud, siis ei tohiks siin olla mitte midagi uut. Teksti saab ekraanile nii:

Erinevaid fonte, mida saab sõna None asemel koodis kasutada saad sa näha käsuga pygame.font.get_fonts(). Kirjuta see käsk käsureale või print() käsuga koodi, siis näed erinevate fontide nimede listi.
Pildid
Piltide lisamine ekraanile on väga lihtne, vaid kaks rida koodi. Esiteks tuleb tekitada muutuja, millele pilt omistatakse ning seejärel tuleb tekitatud muutuja väärtus ekraanile kuvada.
Proovin selle linnu siin oma tulevase mängu aknasse tekitada:

Liikumine
Paneme pildi liikuma!

Lae see pilt alla ning lisa programmiga samasse kausta.
Pildi liigutamine arvutis ei tähenda mitte midagi muud kui pildi uude kohta joonistamist ja vanalt kohalt eelmise pildi ära "kustutamist". Kustutamine aga tähendab arvuti keeles üle värvimist, nii et tekib tunne, et pilt on kustutatud. Kui taust on ühtlase värviga, siis on "kustutamine" kerge, lihtsalt värvime vana pildi tausta värvi ristkülikuga üle. Keeruliseks läheb aga siis, kui taustaks on meil näiteks mõni keeruline maastik või lausa foto, kuidas siis "kustutustöid" teha?
Alustame aga lihtsamast variandist, kus taust on näiteks valge ja paneme siis objekti ekraanil liikuma.


Siin ka video, milles on näide liikuvast linnust lahti seletatud:
Klaviatuurilt juhtimine
Praeguseks
osakme objekti liigutada nii mööda sirgjoont kui mööda kõverjoont, kuid
tahaks ikkagi saada kontrolli ka endale. Kuidas ise liigutada objekti
ekraanil?
Selleks kasutame ära pygame sündmuste toimumise kontrollijat pygame.event.get() ja küsime tema käest, millist klahvi vajutati (pygame.KEYDOWN) ning vastavalt millisele nooleklahvile (K_UP, K_DOWN, K_LEFT, K_RIGHT) vajutati, muudame koordinaate pildi joonistamiseks.


Lisaks nooleklahvidele saab loomulikult sama moodi kontrollida mistahes klahvi vajutust. Kõikide klahvide vastavad käsud leiab pygame.KEYDOWN dokumentatsioonist:
http://www.pygame.org/docs/ref/key.html
Veel on näide sellisest liigutamisest, mis liigutab sammu haaval:

Klaviatuuriga liigutamine - keerulisemalt (vabatahtlik peatükk)
Eelmise näite puudujääk oli see, et näiteks ei saanud korraga kahe klahviga diagonaalis liikuda. Samuti polnud võimalik seisma jääda.
Vaatame ka näidet, milles seda viga pole:

Sündmused, mida saab kontrollida
Eelmisel
lehel vaatasime põhjalikumalt, kuidas enda kontrolli alla võtta
klahvivajutused ja kuidas vastavalt vajutusele saab koodis midagi muuta.
Tegelikult on Pygames palju selliseid sündmuseid mida saab enda
kontrolli alla võtta ja oma soovide järgi kohandada. Kõige tuntumad
nendest on
- KEYDOWN - vaatasime eelmisel lehel
- KEYUP
- QUIT
- MOUSEMOTION
- MOUSEBUTTONUP
- MOUSEBUTTONDOWN
- jne
Kogu nimekirja kõikvõimalikest kontrollsündmustest, näiteks kas või mängukonsoolidega ühinemise jaoks või videote kasutamiseks, leiab aadressilt: http://www.pygame.org/docs/ref/event.html
Kõikide nende nn pygame.event'te kasutamine käib täpselt sama moodi nagu vaatasime KEYDOWN sündmuste kontrolli juures.
Hiirega liigutamine
Klaviatuurilt
objektide liigutamine on lihtne. Kuulad muudkui KEYDOWN'i käskusid ja
kirjutad selle järele if-lausete abil, mis siis juhtuma peaks. Analoogse
süsteemi järgi toimub ka hiirega objektide juhtimine ekraanil. Pidevalt
tuleb kuulata MOUSEMOTION'it ja vastavalt hiire liikumisele kirjutada oma koodi lõik, mis ütleb, mida siis tegema peab kui hiir liigub.
Järgnevalt vaatame kahte näidet hiirega objektide liigutamise kohta. Esimeses näites liigub objekt alati kaasa kui hiir liigub ja teises vaid siis, kui hiirega objektist nö kinni hoida.
Esimene variant on kasulik näiteks ussimängu analoogia
programmeerimisel, kui tahta ussi juhtida hiire kaudu, teine on lihtsalt
igas muus olukorras kasulik
1. näide: objekt liigub siis kui hiir liigub:
2. näide: objekt liigub siis kui hiirega aknale vajutatakse:
Mida õppisid?

Jälle on möödunud üks tegus ja teadmiste rohke nädal. Lisandunud on palju erinevaid koodilõike, mida saab oma tulevastes mängudes ja programmides ära kasutada. Sellel nädalal õppisid:
- Pygame kasutama
- kuidas luua oma mängu akent?
- kuidas sellesse aknasse joonistada ja lisada kujundeid?
- mis asjad on kujundite raamid?
- kuidas kasutatakse värve Pythonis?
- tegema kunsti
- kuidas vabakäe joont teha arvutis?
- kuidas panna erinevate kujundite asukoht üksteisest sõltuma?
- kuidas lisada pilte ekraanile?
- kuidas neid pilte või kujundeid liikuma panna?
- kuidas uuendatakse ekraani pilti?
- kuidas objektid panna liikuma mööda kõverjoont?
- mis asjad on flip() ja blit()?
- kuidas juhtida objekte ekraanil klaviatuuri abil?
- mis asi on sündmuste kontrollija ja kuidas seda ära kasutada?
- kuidas panna objektid liikuma hiire abil?
- said ülevaate teistest kontrollitavatest sündmustest Pygame's, mida oma programmides ära kasutada
